package ua.yandex.collections;

/**
 *
 * @author WslF
 */
public class MyArrayList implements MyList {

    private static final int DEFAULT_CAPACITY = 10;
    private int capacity;
    private int size;
    private Object[] array;

    public MyArrayList() {
        this(DEFAULT_CAPACITY);
    }

    public MyArrayList(int initialCapacity) {
        capacity = initialCapacity;
        array = new Object[capacity];
        size = 0;
    }

    public void ensureCapacity(int minCapacity) {
        if (capacity >= minCapacity) {
            return;
        }
        makeCapacity(minCapacity);
    }

    @Override
    public void add(Object e) {
        checkCapacity();
        array[size++] = e;
    }

    @Override
    public void add(int index, Object e) {
        checkIndex(index);
        checkCapacity();
        System.arraycopy(array, index, array, index + 1, size - index);
        array[index] = e;
        size++;
    }

    @Override
    public void addAll(Object[] c) {
        ensureCapacity(size + c.length);
        System.arraycopy(c, 0, array, size, c.length);
        size += c.length;
    }

    @Override
    public void addAll(int index, Object[] c) {
        checkIndex(index);
        ensureCapacity(size + c.length);
        System.arraycopy(array, index, array, index + c.length, size - index);
        System.arraycopy(c, 0, array, index, c.length);
        size += c.length;
    }

    @Override
    public Object get(int index) {
        checkIndex(index);
        return array[index];
    }

    @Override
    public Object remove(int index) {
        checkIndex(index);
        Object val = array[index];
        System.arraycopy(array, index + 1, array, index, size - index - 1);
        size--;
        checkCapacity();
        return val;
    }

    @Override
    public void set(int index, Object e) {
        checkIndex(index);
        array[index] = e;
    }

    @Override
    public int indexOf(Object o) {
        for (int i = 0; i < size; i++) {
            if (array[i].equals(o)) {
                return i;
            }
        }
        return -1;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public void clear() {
        size = 0;
        makeCapacity(DEFAULT_CAPACITY);
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public Object[] toArray() {
        Object[] ans = new Object[size];
        System.arraycopy(array, 0, ans, 0, size);
        return ans;
    }

    @Override
    public String toString() {
        if (size == 0) {
            return "";
        }
        StringBuilder ans = new StringBuilder(array[0].toString());
        for (int i = 1; i < size; i++) {
            ans.append(", " + array[i].toString());
        }
        return ans.toString();
    }

    private boolean checkIndex(int index) {
        if (index < 0 || index >= size) {
            throw new ArrayIndexOutOfBoundsException(index);
        }
        return true;
    }

    private boolean checkCapacity() {
        if (size == capacity) {
            ensureCapacity(capacity * 2);
            return false;
        }
        if (size < capacity / 2) {
            makeCapacity(capacity / 2);
            return false;
        }

        return true;
    }

    private void makeCapacity(int newCapacity) {
        Object[] newArray = new Object[newCapacity];
        System.arraycopy(array, 0, newArray, 0, Math.min(size, newCapacity));
        array = newArray;
        capacity = newCapacity;
    }

}
